home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Visual Database / Visual dBase Pro v7.0 / DATA1.CAB / Utilities / Web_Wizard / Wizout.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-20  |  54.0 KB  |  1,685 lines

  1. /* Wizout.cc      Output classes for Borland's Visual dBASE 7 Web Wizard
  2.                     (c) 1997 Borland International, all rights reserved
  3.  
  4.    Purpose        These classes perform three functions for the three
  5.                    application types supported by the Web Wizard
  6.  
  7.                Data-Entry Application
  8.                Streams starting HTML page with form and fields 
  9.                Streams .prg for CGI back-end processing (updating rowset)
  10.                Compiles .prg and Builds executable to run server-side
  11.  
  12.                Query and Response Application
  13.                Streams starting HTML page with initial search criteria control
  14.                Modifies .REP file specified by user
  15.                Generates .prg for CGI back-end processing (run report)
  16.                Modifies second .REP file to respond to Href from first report
  17.  
  18.                Publish Application
  19.                Modifies report properties to generate HTML Output to 
  20.                specified web site folder
  21.                Runs report Output to web site folder
  22.  
  23.     Author        A.A.Katz, KSoft, Inc. under contract to Borland
  24.  
  25.     Versions:    Version 1.0 10-14-1997    
  26.  
  27. */
  28.  
  29.  
  30.  
  31.  //////////Class         Wizout///////////////////////////////////////////////////
  32.  //////////Purpose:  Instantiates object, received parent form param//////////
  33.  
  34.  class WizOut(oForm)
  35.  this.cCurrPath = Set('Directory') // store path
  36.  this.oForm = oForm
  37.  this.home = substr(program(1),1,rat('\',program(1)))
  38.  this.bCopyAll = false  
  39.  this.cReportPath = ''
  40.  this.cReportName = ''
  41.  this.cCgiPath = ''
  42.  this.cCgiFolder = ''
  43.  this.cHTMLPath = ''
  44.  this.cClass = ''
  45.  // ////////////////////Method: StreamHTML//////////////////////////
  46.  ///////////////////////Purpose: Generates starting HTML page ///////////////
  47.  ///////////////////////Returns: True, if successful/////////////////////////
  48.  
  49.  /* Note: StreamHTML has four sections in the following order:
  50.           Live Publish Reports
  51.           Static Publish Reports // do nothing
  52.           Data-Entry
  53.           Query
  54.  */
  55.  
  56.  function StreamHTML()
  57.  
  58.  
  59.        ////// no HTML is streamed for live Publish Reports, only CGI
  60.        ////// streaming is done at runtim 
  61.     
  62.        ////// Static Publish Reports
  63.     If this.oForm.cWizardType = 'Publish'
  64.        this.oForm.Progress1.value = 10
  65.        ////// extract names from full path to .REP file
  66.        this.cReportPath = trim(this.oForm.PublishReportField.value)
  67.  
  68.        ////// report name
  69.        if at('\',this.cReportPath) > 0
  70.           this.cReportName = substr(this.cReportPath,;
  71.                rat('\',this.cReportPath)+1)
  72.        else
  73.           this.cReportName = this.cReportPath
  74.        endif
  75.  
  76.        ////// remove extensions
  77.        if at('.',this.cReportName) > 0
  78.           this.cReportName = substr(this.cReportName,1,;
  79.                at('.',this.cReportName)-1)
  80.        endif
  81.  
  82.        this.oForm.Progress1.value = 20
  83.  
  84.        ////// Set up target paths for both publish reports
  85.        if this.oForm.LiveReportRadio.value
  86.           this.oForm.Progress1.value = 90
  87.  
  88.           this.cCGIFolder = trim(this.oForm.PublishCGIField.value)
  89.           if right(this.cCGIFolder,1) # '\'
  90.              this.cCGIFolder += '\'
  91.           endif
  92.           this.oForm.Progress1.value = 0
  93.           return true /////// all done for Live Publish Reports
  94.  
  95.        else
  96.  
  97.           ////// clean up HTML path
  98.           this.cHTMLPath = trim(this.oForm.PublishCGIField.value)
  99.           if right(this.cHTMLPath,1) # '/'
  100.              this.cHTMLPath += '/'
  101.           endif
  102.  
  103.        endif
  104.  
  105.        ////// Paste together HTMLPath for this report
  106.        this.cOutPutPath = this.cHTMLPath+this.cReportName+'.htm'
  107.  
  108.        // Open report file and get classname
  109.  
  110.        this.oForm.Progress1.value = 40
  111.        fRep = new File()
  112.  
  113.        try
  114.  
  115.  
  116.           fRep.Open(this.cReportPath,"R")
  117.          
  118.        catch(Exception e)
  119.  
  120.           msgbox(e.Message,'Fail Open',16)
  121.           return false
  122.  
  123.        endtry
  124.       
  125.        this.cClass = ''
  126.  
  127.  
  128.        ////// Extract classname
  129.        do
  130.           ////// Get next line in .rep file
  131.          
  132.           cStr = Upper(fRep.Gets())
  133.  
  134.           ////// if it's the class definition line
  135.          
  136.           if at('CLASS',cStr) > 0 and at('OF',cStr) > 0 and;
  137.              at('REPORT',cStr) > 0
  138.              
  139.              ////// parse out the class name
  140.              this.cClass = trim( ltrim(  substr(cStr,at('CLASS',cStr)+5) ) )
  141.              this.cClass = trim( ltrim(  substr(this.cClass,1, at(' OF ',this.cClass)-1) ) )
  142.  
  143.              exit
  144.  
  145.           endif
  146.  
  147.        until fRep.eof()
  148.  
  149.        fRep.Close()
  150.        fRep = ''
  151.  
  152.        this.oForm.Progress1.value = 70
  153.  
  154.        ////// No class declaration found
  155.        if len(trim(this.cClass)) = 0
  156.  
  157.           msgbox('Unable to find Report Class in '+this.cReportName,;
  158.                  'Cannot find class',16)
  159.           return false
  160.        endif
  161.  
  162.        ////// try to instantiate the report class
  163.        try
  164.  
  165.          cClass = this.cClass
  166.          set proc to (this.cReportPath) addi   
  167.          this.oRep = new &cClass.()
  168.  
  169.        catch (Exception e)
  170.  
  171.                 ////// if fail, go back
  172.           msgbox(e.Message,'Fail Instantiation',16)
  173.           return false
  174.  
  175.        EndTry
  176.  
  177.        this.oForm.Progress1.value = 80
  178.  
  179.        this.oRep.Output = 4 // HTML
  180.        this.oRep.OutputFileName = this.cOutPutPath
  181.  
  182.        try
  183.           this.oRep.Render()
  184.  
  185.        catch (Exception e)
  186.  
  187.           msgbox('Error rendering report'+chr(13)+;
  188.                   e.message,'Report Error',16)
  189.           return false
  190.        endtry 
  191.  
  192.        this.oForm.Progress1.value = 100
  193.        ////// Clean up
  194.        Close Proc (this.cReportPath)
  195.        this.oRep = ''
  196.  
  197.        this.oForm.Progress1.value = 0
  198.        return true   
  199.               
  200.     endif
  201.  
  202.    
  203.  
  204.     //////////// Wizards that require HTML pages (Query and Data-Entry)
  205.  
  206.     this.bCopyAll = false  // reset "yes to all"
  207.     local n     // init as counter for various loops
  208.     this.BackGroundImage = ''
  209.     this.LogoImage = ''
  210.     this.MailImage = ''
  211.     this.HomeImage = ''
  212.  
  213.     /////////////Make sure output filename is clean
  214.     this.cOutputFile = ltrim(trim(this.oForm.FileNameField.value))
  215.  
  216.     if at('.',this.cOutputFile) > 0
  217.        this.cOutputfile = substr(this.cOutputFile,1,at('.',this.cOutputFile)-1)
  218.     endif
  219.  
  220.     if at('/',this.cOutputFile) > 0
  221.        this.cOutputFile = substr(this.cOutputfile,;
  222.                           rat('\',this.cOutputFile)+1)
  223.     endif
  224.  
  225.  
  226.     //////////Clean up URL and set CGI EXE Name with full web path
  227.     this.cCGIUrl = ltrim(trim(this.oForm.UrlField.value))
  228.     if substr(this.cCgiUrl,len(this.cCgiUrl),1) # '/'
  229.        this.cCgiUrl += '/'
  230.     endif
  231.     if substr(upper(this.cCgiUrl),1,7) # 'HTTP://'
  232.        this.cCgiUrl = 'http://'+this.cCgiUrl
  233.     endif
  234.     this.cCgiUrlBat = this.cCgiUrl+this.cOutputFile+'.Bat'
  235.  
  236.  
  237.     //////////////// Initialize and test CGI folder
  238.     this.cCgiPath = this.oForm.CGIPathField.value
  239.     if empty(this.cCGIPath)
  240.        return false
  241.     endif
  242.     this.cCgiPath = Class::CleanUpFolder(this.cCGIPath)
  243.  
  244.     this.cCgiFileName = this.cCgiPath+this.cOutputFile+'.exe'
  245.     //CGI path is formatted properly and tested
  246.  
  247.  
  248.     this.cCGIFolder = this.cCgiPath
  249.  
  250.  
  251.     /////////////// Initialize and test HTML folder
  252.     this.cHTMLPath = this.oForm.HTMLPathField.value
  253.     if empty(this.cHTMLPath)
  254.        msgbox('Web Site HTML path required to finish application.')
  255.        return false
  256.     endif
  257.     this.cHtmlPath = Class::CleanUpFolder(this.cHTMLPath)
  258.     
  259.             //HTML path is formatted properly and tested
  260.  
  261.        
  262.  
  263.             //Add HTML Path to HTML File name
  264.     this.cHtmlFileName = this.cHtmlPath+this.cOutputFile+'.htm'
  265.  
  266.             // test for duplicates 
  267.     if file(this.cHTMLFileName)
  268.        if msgbox('Filename: '+this.cHTMLFileName+' already exists! '+;
  269.           'Overwrite?','Duplicate Filename',36) # 6
  270.           return false
  271.        endif
  272.        dele file (this.cHTMLFileName)
  273.     endif
  274.  
  275.         // get reportpath and reportname                         
  276.     this.cReportPath = trim(this.oForm.FirstReportField.value)
  277.      ////// report name
  278.     if at('\',this.cReportPath) > 0
  279.        this.cReportName = substr(this.cReportPath,;
  280.             rat('\',this.cReportPath)+1)
  281.     else
  282.        this.cReportName = this.cReportPath
  283.     endif
  284.     ////// remove extensions
  285.     if at('.',this.cReportName) > 0
  286.        this.cReportName = substr(this.cReportName,1,;
  287.             at('.',this.cReportName)-1)
  288.     endif
  289.     
  290.     //////////// Copy in graphic images for background, home and mail
  291.     //////////// Note: bad files or paths are not treated as critical
  292.     //////////// errors since the Browser just puts a "broken image"
  293.     //////////// logo on the HTML page. Warnings, however, are given
  294.  
  295.     //////////// each image is removed from datasources so that it can
  296.     //////////// be copied, and then restored when done.
  297.     this.oform.progress1.value = 10
  298.     cd (this.home)  // go back to home directory
  299.  
  300.            cBkg = this.oForm.Background
  301.            cDsc = this.oForm.BackgroundDisplay.DataSource
  302.            this.oForm.Background = 'FILENAME Blank.gif'
  303.            this.oForm.BackgroundDisplay.DataSource = 'FILENAME Blank.gif'
  304.     
  305.     this.BackgroundImage     = class::CopyGraphicFile(this.oForm.BackgroundImageField.value)
  306.            this.oForm.Background = cBkg
  307.            this.oForm.BackgroundDisplay.DataSource = cDsc
  308.    
  309.  
  310.            cDsc = this.oForm.HomeImage.DataSource
  311.            this.oForm.HomeImage.DataSource = 'FILENAME Blank.gif'
  312.            
  313.     this.HomeImage             = class::CopyGraphicFile(this.oForm.HomeImageField.value)
  314.            this.oForm.HomeImage.DataSource = cDsc
  315.         
  316.  
  317.            cDsc = this.oForm.MailImage.DataSource
  318.            this.oForm.MailImage.DataSource = 'FILENAME Blank.gif'
  319.           
  320.     this.MailImage = class::CopyGraphicFile(this.oForm.MailImageField.value)
  321.            this.oForm.MailImage.DataSource = cDsc
  322.           
  323.  
  324.            cDsc = this.oForm.LogoImage.DataSource
  325.            this.oForm.LogoImage.DataSource = 'FILENAME Blank.gif'
  326.            
  327.     this.LogoImage            = class::CopyGraphicFile(this.oForm.LogoImageField.value)
  328.            this.oForm.LogoImage.DataSource = cDsc
  329.          
  330.  
  331.     this.oform.progress1.value = 40
  332.  
  333.     // Create HTML file with low-level IO
  334.  
  335.     if file(this.cHtmlFileName)
  336.        dele file (this.cHtmlFileName)
  337.     endif
  338.     this.nHnd = fCreate(this.cHtmlFileName)
  339.  
  340.     if this.nHnd < 0
  341.        msgbox('Cannot create: '+this.cHtmlFileName )
  342.        return false
  343.     endif
  344.  
  345.  
  346.     // Stream Header
  347.  
  348.     fPuts(this.nHnd,'<HTML>')
  349.     fPuts(this.nHnd,'')
  350.     fPuts(this.nHnd,'<head>')
  351.     fPuts(this.nHnd,'<meta http-equiv="Content-Type" content="text/html">')
  352.     fPuts(this.nHnd,'<meta name="Generator" content="Visual dBASE 7 Web Wizard">')
  353.     if not empty(this.oForm.FirstPageTitle.Editor1.value)
  354.        fPuts(this.nHnd,'<title>'+this.oForm.FirstPageTitle.Editor1.value+'</Title>')
  355.     endif
  356.     fPuts(this.nHnd,'</head>')
  357.     fPuts(this.nHnd,'')
  358.  
  359.     this.oform.progress1.value = 50
  360.  
  361.     fPuts(this.nHnd,'   '+class::BuildBodyString())
  362.     fPuts(this.nHnd,'')
  363.     fPuts(this.nHnd,'   <blockquote>')
  364.  
  365.     class::StreamTitleAndLogo()
  366.  
  367.     fPuts(this.nHnd,'')
  368.     cHtml = class::BuildHTMLString(this.oForm.TextAboveDataEntry)
  369.     if not empty(cHTML)
  370.        fPuts(this.nHnd,'      '+cHTML)
  371.     endif
  372.  
  373.     fPuts(this.nHnd,'')
  374.     fPuts(this.nHnd,'      <Form METHOD="Get" Action="'+this.cCgiUrlBat+'">')
  375.     fPuts(this.nHnd,'')
  376.             // stream form controls
  377.     class::StreamDataControls()
  378.  
  379.           // submit and reset buttons
  380.     cAlign = iif(this.oform.cWizardType = 'Query','center',;
  381.                  iif(this.oForm.AlignDataCenterRadio.value,'center',;
  382.                  'left'))
  383.     fPuts(this.nHnd,'         <DIV align="'+cAlign+'"><p></p><p><Input type="Submit" value="Submit" > '+;
  384.                              '<Input type="Reset" value = "Reset"></p></DIV>')
  385.     
  386.  
  387.     fPuts(this.nHnd,'      </Form>')
  388.  
  389.     fPuts(this.nHnd,'')
  390.     cHTML = class::BuildHTMLString(this.oForm.TextBelowDataEntry)
  391.     if not empty(cHTML)
  392.        fPuts(this.nHnd,'      '+cHTML)
  393.     endif
  394.  
  395.     this.oform.progress1.value = 70
  396.  
  397.     class::StreamHomeandMail()
  398.     
  399.     this.oForm.progress1.value = 90
  400.  
  401.     fPuts(this.nHnd,'   </blockquote>')
  402.     fPuts(this.nHnd,'   </body>')
  403.     fPuts(this.nHnd,'</HTML>')
  404.     fClose(this.nHnd)
  405.     this.oform.progress1.value = 100
  406.     this.oform.progress1.value = 0
  407.     this.oform.finishlabel.text = 'Progress...'
  408.  
  409.     return true
  410.     
  411.     // Initialize URL
  412.  
  413.     ///////////Method: StreamtitleandLogo ////////////////////////////////
  414.     //////////Purpose: Outputs title and logo image
  415.  
  416.     function StreamTitleAndLogo
  417.  
  418.        local cTitle
  419.        cTitle = ltrim(trim(class::BuildHTMLString(this.oForm.FirstPageTitle)))
  420.             // if title and logo on same line and both exist
  421.  
  422.        if this.oform.LeftOfTitleRadio.value and ;
  423.           (not empty(this.logoImage)) and ;
  424.           (not empty(this.oForm.firstPageTitle.editor1.value))
  425.           
  426.              // adjust tags to combine graphic and text in same line.
  427.              local cFirst, cLast
  428.              cFirst = ''
  429.              cLast = ''
  430.              if substr(cTitle,1,2) = '<H'
  431.                 //save begining of "header"
  432.                 cFirst = substr(cTitle,1,at('>',cTitle))
  433.                 //remove H tag and H end tag
  434.                 cTitle = substr(cTitle,at('>',cTitle)+1)
  435.                
  436.                
  437.              endif
  438.           fPuts(this.nHnd,'      '+cFirst+'<img src="'+this.LogoImage+'"> '+ cTitle)
  439.       
  440.        else
  441.  
  442.               // Display logo at center or left, depending on radiobuttons
  443.           if not empty(this.logoImage)
  444.              cHtml = '         <p align="'
  445.              cHtml+= iif(this.oform.TopCenterRadio.value,'center','left')
  446.              cHtml+= '">'
  447.              cHtml+='<img src="'+this.LogoImage+'">'
  448.              cHtml+= '</p>'
  449.  
  450.              fPuts(this.nHnd,cHtml)
  451.                  // start a new line
  452.           endif
  453.           
  454.             // Display title of page, if there is one
  455.           if not empty(cTitle)
  456.              fPuts(this.nHnd,'         '+cTitle)             
  457.           endif
  458.  
  459.  
  460.        endif
  461.  
  462.        return true
  463.  
  464.  
  465.  
  466.    ///////////Method:  CopyGraphicFile ///////////////////////////////
  467.     ///////////Purpose: Copies graphic files from source folder to
  468.     ///////////         HTML folder
  469.  
  470.     Function CopyGraphicFile(cSource)    
  471.  
  472.        local cSourcePath, cFileName, cDestPath, cSaveSource 
  473.  
  474.        
  475.        cSourcePath = trim(ltrim(cSource))
  476.       
  477.        
  478.                    // see if no file specified
  479.        if len(cSourcePath) = 0
  480.           return ''
  481.        endif
  482.  
  483.                //hard wire default path!
  484.        if at('\',cSourcePath) = 0
  485.           cSourcePath = trim(this.home)+cSourcePath
  486.        endif
  487.  
  488.                //Strip out path to extract filename
  489.        cFileName = trim(cSourcePath)
  490.  
  491.        if at('\',cFileName) > 0
  492.           cFileName = substr(cFileName,rat('\',cFileName)+1)
  493.        endif
  494.  
  495.                //Define destination path
  496.        cDestPath = this.cHTMLPath+cFileName
  497.  
  498.         
  499.             // This is a workaround of the "File Exists... Overwrite"
  500.             // automatic dialog in order to do a "copy all"
  501.  
  502.             // if file already exists
  503.        if file(cDestPath)   
  504.             // and they didn't already say 'Yes to all"
  505.           if not this.bCopyAll
  506.                      // if they say "dont' overwrite"
  507.              if not class::OverwriteFile(cDestPath)
  508.                         //forget it
  509.                 return cFile
  510.              else
  511.                          //otherwise, delete the file so no
  512.                      //"overwrite" msgbox() will appear
  513.                 dele file (cDestPath)
  514.              endif
  515.  
  516.           else
  517.                  // if it is already "copyall"
  518.                  // delete the file before copying
  519.              dele file (cDestPath)
  520.  
  521.           endif
  522.        endif
  523.  
  524.            // Try to copy file to HTML folder
  525.        try
  526.  
  527.           Copy File (cSourcePath) to (cDestPath)
  528.  
  529.        catch (Exception e)
  530.  
  531.           msgbox('Cannot copy file '+cSourcePath+' to '+cDestPath+;
  532.                  chr(13)+e.message,'Copy Error',16)
  533.        endtry
  534.  
  535.        
  536.  
  537.        Return cFileName
  538.  
  539.  
  540.     ////////////Method: BuildBodyString ////////////////////////////
  541.     ////////////Purpose: Builds string for HTML body attributes
  542.     function BuildBodyString
  543.  
  544.  
  545.     local cBody
  546.     cBody = '<body '
  547.     if not empty(this.oForm.BackgroundColorField.value)
  548.        cBody += 'bgcolor="'+;
  549.                  class::HTMLColor(this.oForm.BackgroundcolorField.value)+;
  550.                  '"'
  551.     endif
  552.     if not empty(this.BackGroundImage)
  553.        cBody += ' background="'+this.BackgroundImage+'"'
  554.     endif
  555.     cBody +='>'
  556.     return cBody
  557.  
  558.  
  559.  
  560.  
  561.  
  562.     ///////////Method: HTMLColor ///////////////////////////////////
  563.     ///////////Purpose: Converts VdB color string to HTML color string
  564.     ///////////            VdB colors are:  0xBGR
  565.     ///////////         HTML colors are: #RGB
  566.     function HTMLColor(cColor)
  567.               // if not a dBASE color string
  568.       if at('0X',upper(cColor)) = 0
  569.          return cColor
  570.       endif
  571.               // X0BBGGRR
  572.       return '#'+substr(cColor,7,2)+substr(cColor,5,2)+;
  573.          substr(cColor,3,2)
  574.     
  575.  
  576.  
  577.  
  578.  
  579.  
  580.  
  581.     ///////////Method: Stream Data Controls ///////////////////////////
  582.     ///////////Purpose: Streams out controls for query and data-entry
  583.     
  584.     Function StreamDataControls 
  585.  
  586.        // If this is a query page, stream query "get" controls
  587.  
  588.        if this.oForm.cWizardType = 'Query'
  589.  
  590.                  // if it's a combobox (select) with options
  591.           fPuts(this.nHnd,'')
  592.  
  593.           cHtml  = '         <Center><P><P>'
  594.           if this.oForm.ComboboxRadio.value
  595.  
  596.  
  597.             
  598.              cHtml += '         <Select name="SEARCH" size="1">'
  599.              for n = 1 to alen(this.oform.aOptions,1)
  600.                 cOption = this.oForm.aOptions[n]
  601.                 cHtml+= '         <Option value="'+cOption+'">'+cOption+;
  602.                          '</Option>'
  603.              next
  604.              cHtml+='         </Select></P></P></DIV>'
  605.       
  606.           else  // if it's a text field
  607.  
  608.             
  609.              cHtml =  '         <DIV align="center"><P><P>'
  610.              cHtml += '         <Input type="Text" name="SEARCH" size="25">'
  611.              cHtml += '         </P></P></DIV>'
  612.  
  613.       
  614.           endif
  615.           fPuts(this.nHnd,cHtml)
  616.           fPuts(this.nHnd,'')
  617.  
  618.  
  619.           return true
  620.  
  621.  
  622.  
  623.        endif
  624.                //////////////////End of Query Wizard data object streaming
  625.  
  626.                //////////////////The following is for Data-Entry Wizard
  627.   
  628.             // Check if there are any selected fields!
  629.        if alen(this.oForm.aSelectedFields,1) = 0
  630.           return false      //if not, forget it
  631.        endif
  632.  
  633.             // Initialize data-source properties (for datamodule or table)
  634.        this.cSource = trim(this.oForm.DataSourceField.value)
  635.        this.cFile = iif(at('\',this.cSource) > 0,substr(this.cSource,;
  636.                     rat('\',this.cSource)+1),this.cSource)
  637.                                        
  638.             // number of field objects to be streamed
  639.        nNumFields = alen(this.oForm.aSelectedFields,1)
  640.                    
  641.                                                          
  642.  
  643.  
  644.  
  645.  
  646.                // open query or table
  647.        if at('.DMD',this.cFile) > 0
  648.  
  649.           this.cDataType = 'Data Module'
  650.           // get datamodule reference from file
  651.         
  652.  
  653.           ////////// open datamodule source file using low-level File I/O
  654.           ////////// uses this.nH, since this.nHnd is already open
  655.           fDmd = new File()
  656.           try
  657.              fDmd.Open(this.cSource,"R")
  658.           catch (Exception e)
  659.                                   // if this fails, error and return
  660.              msgbox('Unable to open disk file '+this.cSource)
  661.              return false
  662.           endtry
  663.  
  664.  
  665.           ////////////////////// Extract .DMD data module class name
  666.           cDmd = ''
  667.           cStr = upper(fDmd.Gets())
  668.                            // loop through source looking for class statement
  669.           do 
  670.  
  671.              
  672.              if at('CLASS',cStr) > 0 and at('OF DATAMODULE',cStr) > 0
  673.                 cDmd = trim(ltrim(substr(cStr,at('CLASS',cStr)+5)))
  674.                 cDmd = trim(ltrim(substr(cDmd,1,at('OF DATAMODULE',cDmd)-1)))                    
  675.                 exit
  676.              endif
  677.  
  678.              cStr = upper(fDmd.gets())
  679.           
  680.           until fDmd.Eof()
  681.  
  682.           fDmd.Close()    // close disk file
  683.  
  684.  
  685.           if len(trim(cDmd)) = 0        // if no class found, go back
  686.              msgbox('Cannot find Data Module class in '+this.cSource)
  687.              return false
  688.           endif
  689.  
  690.           ////////////////open data///////////////////////////////////////
  691.               
  692.           try
  693.  
  694.              this.dMod = new &cDmd.()  // go ahead, instantiate data module
  695.  
  696.           catch (Exception e)
  697.  
  698.              msgbox('Unable to open Data Module '+this.cSource+chr(13);
  699.                     +e.message)
  700.              return false
  701.  
  702.           endtry
  703.  
  704.  
  705.        else     // this is a table, not a data module
  706.  
  707.           this.cDataType = 'Table'
  708.  
  709.           ///////////////open data
  710.  
  711.           try
  712.  
  713.              this.q = new Query()
  714.              this.q.SQL = 'Select * from "'+this.cSource+'"'
  715.              this.q.active = true
  716.  
  717.           catch (Exception e)
  718.  
  719.              msgbox('Unable to open table '+this.cSource,'Open Error',16)
  720.              return false
  721.  
  722.           endtry 
  723.  
  724.        endif  // endif .dmd or table
  725.  
  726.  
  727.        // start table
  728.  
  729.                // Store table alignment for shorthand
  730.        cAlign = iif(this.oForm.AlignDataCenterRadio.value,'center','left')
  731.  
  732.        fPuts(this.nHnd,'         <DIV align="'+cAlign+'">')
  733.        fPuts(this.nHnd,'         <Table border="0"'+;
  734.                   ' cellpadding="4" cellspacing="0">')
  735.  
  736.                // for manipulation purposes, store referece to form's 
  737.             // selected fields array in aSelect
  738.             // sSelect preserves the user's field order
  739.  
  740.  
  741.        aSelect = this.oForm.aSelectedFields
  742.  
  743.        for n = 1 to alen(aSelect,1)
  744.           
  745.                   //parse out query/name pairs of array element
  746.           cLookup       = ltrim(trim(aSelect[n]))
  747.           cQuery             = substr(aSelect[n],1,at('->',aSelect[n])-1)
  748.           cName              = trim(substr(aSelect[n],at('->',aSelect[n])+2))
  749.  
  750.                   //get the type of control needed///////////////
  751.                //as well as length and decimals
  752.  
  753.           if this.cDataType = 'Table'
  754.              this.q.rowset.first()
  755.              cType      = this.q.rowset.fields[cName].type
  756.              nLen       = this.q.rowset.fields[cName].length
  757.              nDecs      = this.q.rowset.fields[cName].decimalLength
  758.           else
  759.              cType         = 'this.dMod.'+cQuery+'.rowset.fields["'+;
  760.                            cName+'"].type'
  761.              cType         = &cType.
  762.              cLen       = 'this.dMod.'+cQuery+'.rowset.fields["'+;
  763.                            cName+'"].length'
  764.              nLen       = &cLen.             
  765.              cDecs      = 'this.dMod.'+cQuery+'.rowset.fields["'+;
  766.                            cName+'"].decimalLength'
  767.              nDecs      = &cDecs
  768.           endif
  769.                   //String length for HTML usage
  770.           cLen       = ltrim(trim(str(nlen,4)))
  771.  
  772.                   // Look up user-defined label for this item (if any)
  773.                // in query Wiztemp1
  774.           cLabel = ''
  775.           
  776.           this.oForm.Wiztemp1.Rowset.Applylocate("Field = '"+cLookup+"'")
  777.           if .not. this.oForm.Wiztemp1.Rowset.EndOfset
  778.              cLabel = trim(this.oForm.Wiztemp1.Rowset.Fields['Label'].value)
  779.           endif
  780.           xName = cQuery+'*@'+cName
  781.           cType = upper(cType)
  782.  
  783.           fPuts(this.nHnd,'         <tr>')                    // add table row  
  784.  
  785.           fPuts(this.nHnd,'            <td>'+cLabel+'</td>')  // Add label cell contents
  786.  
  787.           cHtml ='            <td>'                           // add control cell
  788.  
  789.           if cType = 'MEMO'
  790.              cHtml+='<textarea rows="2" cols="30" name= "'+xName+'"></textarea>'            
  791.           elseif cType     = 'LOG'
  792.              cHtml+='<Input type="checkbox" value="OFF" name="'+xName+'">' 
  793.           else        
  794.              cHtml+='<Input type="text" size="'+cLen+'" name="'+xName+'">'
  795.           endif   
  796.  
  797.           cHtml+= '</td>'
  798.  
  799.           fPuts(this.nHnd,cHtml)
  800.  
  801.           fPuts(this.nHnd,'         </tr>')
  802.  
  803.        next
  804.  
  805.        fPuts(this.nHnd,'         </Table></DIV>')
  806.  
  807.         return true
  808.  
  809.    //////////Method:  StreamHomeAndMail ///////////////////////////////////////
  810.    ////// ///Purpose: Streams out GIFs or text for Home and Mail
  811.  
  812.    Function StreamHomeAndMail
  813.  
  814.    local bDoMail, bDoHome, cHTML, bParaDone
  815.    cAlign = iif(this.oForm.cWizardType = 'Query' or ;
  816.             (this.oForm.cWizardType = 'Data' and ;
  817.             this.oForm.AlignDataCenterRadio.value),;
  818.             'center','left')
  819.  
  820.       cHtml = ''
  821.       bParaDone = false
  822.  
  823.             //first find out if the addresses and info needed exist
  824.       bDoHome = not( empty(this.oform.HomeImageField.value) or;
  825.                      empty(this.oform.HomeURLField.value) )
  826.       bDoMail = not( empty(this.oform.MailImageField.value) or;
  827.                      empty(this.oform.MailAddressField.value) )
  828.  
  829.  
  830.       if bDoHome
  831.          if not bParaDone
  832.             cHtml+= '<DIV align="'+cAlign+'"><p></p>'
  833.             bParaDone = true
  834.          endif
  835.  
  836.          cUrl = trim(ltrim(this.oForm.HomeUrlField.value))
  837.          if substr(upper(cUrl),1,7) # 'HTTP://'
  838.             cUrl = 'http://'+cUrl
  839.          endif
  840.          
  841.          if this.oForm.UseTextRadio.value
  842.            cHtml += ;
  843.                '<a href="'+cUrl+'">'+;
  844.                trim(ltrim(this.oForm.HomeImageField.value))+;
  845.                '</a>'
  846.          else
  847.            cHtml += ;
  848.                '<a href="'+cUrl+'">'+;
  849.                '<img src="'+trim(this.HomeImage)+'" border="0">'+;
  850.                '</a>'
  851.                
  852.          endif
  853.  
  854.       endif
  855.  
  856.       if bDoMail
  857.          if not bParaDone
  858.             cHtml+= '<DIV align="'+cAlign+'"><p></p>'
  859.             bParaDone = true
  860.          endif
  861.  
  862.          if this.oForm.UseTextRadio.value
  863.            cHtml += ;
  864.                ' <a href="mailto:'+trim(ltrim(this.oform.MailAddressField.value))+'">'+;
  865.                trim(ltrim(this.oForm.MailImageField.value))+;
  866.                '</a>'
  867.          else
  868.            cHtml += ;
  869.                ' <a href="mailto:'+trim(ltrim(this.oform.MailAddressField.value))+'">'+;
  870.                '<img src="'+trim(this.Mailimage)+'" border="0">'+;
  871.                '</a>'
  872.                
  873.          endif
  874.       endif
  875.  
  876.       if bParaDone
  877.          cHtml += '</DIV>'
  878.          fPuts(this.nHnd,'      '+cHtml)
  879.       endif
  880.       return cHtml
  881.  
  882.  
  883.  
  884.    //////////Method: CleanUpFolder
  885.    //////////Purpose:Returns path trimmed with trailing backslash
  886.    function CleanUpFolder(cPath)
  887.       cPath = ltrim(trim(cPath))
  888.       if substr(cPath,len(cPath),1) # '\'
  889.          cPath +='\'
  890.       endif
  891.       
  892.       return cPath
  893.  
  894.  
  895.  
  896.    ///////////////Method: BuildHTMLString////////////////////////////
  897.    ///////////////Purpose: Reads HTMLget Container properties to
  898.    ///////////////         stream out HTML text
  899.    ///////////////Param:   Reference to HTML container on parent form
  900.  
  901.    function BuildHTMLString(oText)
  902.  
  903.       
  904.       /* before you build HTML tagged string, remove any tags
  905.          that may already exist
  906.  
  907.       */
  908.       cStr = oText.Editor1.Value
  909.  
  910.       if empty(cStr)
  911.          return ''
  912.       endif
  913.  
  914.       
  915.       // first, strip off endtags (if any)
  916.       if at('</',cStr) > 0
  917.          
  918.          cStr = substr(cStr,1,at('</',cStr)-1)
  919.  
  920.       endif
  921.      
  922.         // Now, get rid of starting tags
  923.       do while at('>',cStr) > 0
  924.  
  925.          cStr = substr(cStr,at('>',cStr)+1)
  926.  
  927.       enddo
  928.  
  929.       
  930.       // Next, build string from "inside-out"
  931.  
  932.       // Attributes first
  933.  
  934.      
  935.  
  936.       if at('Underline',oText.AttribCombo.value) > 0
  937.          cStr = '<U>'+cStr+'</U>'
  938.       endif
  939.       if at('Bold',oText.AttribCombo.value) > 0
  940.          cStr = '<B>'+cStr+'</B>'
  941.       endif
  942.       if at('Italic',oText.AttribCombo.value) > 0
  943.          cStr = '<I>'+cStr+'</I>'
  944.       endif   
  945.  
  946.       
  947.  
  948.  
  949.       // Then, color and alignment
  950.                                      //+o
  951.       cStr = '<Font color="'+class::htmlColor(oText.ColorField.value)+'">'+;
  952.               cStr+'</Font>'
  953.   
  954.      
  955.  
  956.       // Then, text style
  957.  
  958.       if at('Header',oText.FontCombo.value) > 0
  959.          cStr = '<H'+ substr(oText.FontCombo.value,8,1)+;
  960.                 ' align='+iif(oText.AlignLeftRadio.value,'left','center')+;
  961.                 '>'+cStr+'</H'+substr(oText.FontCombo.value,8,1)+'>'
  962.  
  963.       else
  964.          // Paragraph,alignment:
  965.          cStr = '<P '+'align='+iif(oText.AlignLeftRadio.value,;
  966.              "left", "center")+'>'+cStr+'</P>'
  967.       endif
  968.  
  969.       return cStr 
  970.  
  971.  
  972.    /////////  Method:  OverwriteFile ///////////////////////////////
  973.    /////////  Purpose: Special msgbox() for overwriting existing files
  974.    /////////           with a "yes to all" 
  975.    Function OverWriteFile(cFileName)
  976.       this.bOverWrite = false
  977.  
  978.  
  979.       this.oF = new form()
  980.       with (this.oF)
  981.          scaleFontBold = false
  982.          height = 4.5909
  983.          left = 26.7143
  984.          autocenter = true
  985.          top = 3
  986.          width = 49.2857
  987.          mdi = false
  988.          text = "Overwrite"
  989.       endwith
  990.       this.oF.oParent = this
  991.  
  992.       this.oF.IMAGE1 = new IMAGE(this.oF)
  993.       with (this.oF.IMAGE1)
  994.          height = 1.5455
  995.          left = 0.2857
  996.          top = 0.3182
  997.          width = 5.7143
  998.          metric = 0    // Chars
  999.          dataSource = "FILENAME Question.bmp"
  1000.          alignment = 4    // True Size
  1001.          borderStyle = 3    // None
  1002.       endwith
  1003.  
  1004.  
  1005.       this.oF.TEXT1 = new TEXT(this.oF)
  1006.          with (this.oF.TEXT1)
  1007.          height = 1.8182
  1008.          left = 8.1429
  1009.          top = 0.7273
  1010.          width = 37.1429
  1011.          metric = 0    // Chars
  1012.          colorNormal = "BtnText/BtnFace"
  1013.          fontSize = 8
  1014.          fontName = 'MS Sans Serif'        
  1015.          text = '<p align="Center">'
  1016.          text+= 'File: '+trim(cFileName)+' already exists! Overwrite?'
  1017.          text+= '</p>'
  1018.       endwith
  1019.  
  1020.  
  1021.       this.oF.YESBUTTON = new PUSHBUTTON(this.oF)
  1022.       with (this.oF.YESBUTTON)
  1023.          onClick = {;form.oParent.bOverWrite = true;form.close()}
  1024.          height = 0.9545
  1025.          left = 7.5714
  1026.          top = 3.1364
  1027.          width = 10.7143
  1028.          text = "&Yes"
  1029.          metric = 0    // Chars
  1030.          fontSize = 8
  1031.          group = false
  1032.          colorNormal = "BtnText/BtnFace"
  1033.          value = false
  1034.       endwith
  1035.  
  1036.  
  1037.       this.oF.YESTOALLBUTTON = new PUSHBUTTON(this.oF)
  1038.       with (this.oF.YESTOALLBUTTON)
  1039.          onClick = {;form.oParent.bOverWrite = true;form.oParent.bCopyAll=true;form.close()}
  1040.          height = 0.9545
  1041.          left = 19.2857
  1042.          top = 3.1364
  1043.          width = 10.7143
  1044.          text = "Yes to &All"
  1045.          metric = 0    // Chars
  1046.          fontSize = 8
  1047.          group = false
  1048.          colorNormal = "BtnText/BtnFace"
  1049.          value = false
  1050.       endwith
  1051.  
  1052.       this.oF.NOBUTTON = new PUSHBUTTON(this.oF)
  1053.       with (this.oF.NOBUTTON)
  1054.          onClick = {;form.close()}
  1055.          height = 0.9545
  1056.          left = 31
  1057.          top = 3.1364
  1058.          width = 10.7143
  1059.          text = "&No"
  1060.          metric = 0    // Chars
  1061.          fontSize = 8
  1062.          group = false
  1063.          colorNormal = "BtnText/BtnFace"
  1064.          value = false
  1065.       endwith
  1066.  
  1067.       ?? chr(7)
  1068.       this.oF.ReadModal()
  1069.       return this.bOverWrite
  1070.  
  1071.  
  1072.  
  1073.    ///////////Method:     StreamCGI  ///////////////////////////////////////////
  1074.    ///////////Purpose:  The other main method of class Out ///////////////////
  1075.    ///////////          this method streams .prgs and bat files and //////////
  1076.    ///////////          compiles and generates an .EXE  //////////////////////
  1077.    function StreamCGI
  1078.  
  1079.       ///////////////// don't do it if it's a static publish
  1080.       ///////////////// all others stream CGI
  1081.  
  1082.       if this.oForm.cWizardType = 'Publish' and ;
  1083.          not this.oForm.LiveReportRadio.value
  1084.          return true
  1085.       endif
  1086.  
  1087.       this.oForm.Finishlabel.text = 'Streaming CGI code...'
  1088.       this.oForm.Finishlabel.visible  = false // workaround for display prob.
  1089.       this.oForm.Finishlabel.visible = true
  1090.   
  1091.  
  1092.       Local n
  1093.       this.cClass = ''
  1094.       this.cDataType = 'Table'
  1095.  
  1096.       this.oForm.Finishlabel.Text = 'Streaming CGI...'
  1097.       this.oForm.progress1.value = 10
  1098.    
  1099.       ///////////////////Data-Entry Wizard setup /////////////////////////
  1100.       if this.oForm.cWizardType = 'Data Entry'
  1101.        ///// Paste up .prg path 
  1102.          cPrgName = trim(this.oForm.FileNameField.value)
  1103.          cPrgPath = this.cCGIFolder+cPrgName+'.prg'
  1104.  
  1105.          /// this is for compatibility with the other wizards
  1106.          this.cReportName = cPrgName
  1107.          this.cReportPath = cPrgPath
  1108.  
  1109.          // Create an array for compile and build
  1110.          this.aObj = new array()
  1111.          this.aObj.add(cPrgPath)
  1112.          
  1113.    
  1114.  
  1115.          //Extract the datamodule name from the source file
  1116.          cQueryName = ''   
  1117.          cDmodName = ''
  1118.          cQueryName = ''
  1119.          this.cDataPath = trim(this.oForm.dataSourceField.value)
  1120.  
  1121.          if upper(right(this.cDataPath,4)) = '.DMD'
  1122.             this.cDataType = 'Datamodule'
  1123.             this.aObj.add(this.cDataPath)
  1124.  
  1125.             ////// try to open the .dmd file
  1126.             try
  1127.                fDmd = new File()
  1128.                fDmd.Open(trim(this.cDataPath),"R")
  1129.             catch (Exception e)
  1130.                msgbox(e.message,'Data Module Open Error',16)
  1131.                return false
  1132.             endtry
  1133.  
  1134.             do
  1135.  
  1136.                cStr = trim(fDmd.Gets(this.nHnd))
  1137.  
  1138.                ////// if class declaration is found
  1139.                if at('CLASS ',upper(cStr)) > 0 and at('OF',upper(cStr)) > 0
  1140.                                                         // get class name
  1141.                   cStr = ltrim(substr(cStr,at('CLASS',upper(cStr))+5))           
  1142.                   cDModName = trim(substr(cStr,1,at(' ',cStr)-1))
  1143.                   exit
  1144.                endif
  1145.  
  1146.             until fDmd.Eof()
  1147.  
  1148.             fDmd.Close()
  1149.             fDmd = ''
  1150.  
  1151.               // if no data module class name is found, forget it!
  1152.             if len(trim(cDmodName)) = 0
  1153.                  msgbox('Cannot find class declaration in: '+cDataPath,;
  1154.                         'Data Module Error',16)
  1155.                  return false
  1156.             endif
  1157.  
  1158.          else  // if it's a table
  1159.  
  1160.             this.cDataType = 'Table'
  1161.             ////// get table name to use as query name
  1162.  
  1163.             cQueryName = substr(this.cDataPath,1, rat('.',this.cDataPath)-1)
  1164.  
  1165.             if at('\',cQueryName) > 0
  1166.                cQueryName = substr(cQueryName,rat('\',this.cDataPath)+1)
  1167.             endif
  1168.         
  1169.          endif
  1170.  
  1171.  
  1172.       ////////// if this is a live publish or query
  1173.       else
  1174.  
  1175.            ///// Paste up .prg path 
  1176.          cPrgPath = this.cCGIFolder+This.cReportName+'.prg'
  1177.          cPrgName = this.cReportName+'.prg'
  1178.  
  1179.  
  1180.          // Create an array for compile and build
  1181.          this.aObj = new array()
  1182.          this.aObj.add(cPrgPath)
  1183.          this.aObj.add(this.cReportPath)
  1184.  
  1185.          this.oForm.progress1.value = 10
  1186.          ////// open the report file and check for "set procedure" statements
  1187.          ////// While doing that, get the report's class name, too.
  1188.  
  1189.  
  1190.          fRep = new File()
  1191.       
  1192.          try
  1193.             fRep.Open(this.cReportPath,'R')
  1194.  
  1195.          catch (Exception e)
  1196.  
  1197.             msgbox(e.message,'Fail Report Open',16)
  1198.             return false
  1199.          endtry
  1200.  
  1201.          do
  1202.  
  1203.             ////// parse out each line for a set proc statement
  1204.             cStr = upper(fRep.Gets())
  1205.             if at('SET PROC',cStr) > 0
  1206.                ////// if found, get the path and add it to the array
  1207.                cProc = trim( ltrim( substr(cStr,at(' TO ',cStr)+3) ) )
  1208.                ////// remove any "additive" statements
  1209.                if at('ADDI',upper(cProc))
  1210.                   cProc  = ltrim(trim(substr(cProc,1,at('ADDI',cProc)-1)))
  1211.                endif
  1212.                this.aObj.add(cProc)
  1213.             endif
  1214.  
  1215.             ////// get class name
  1216.             if at('CLASS',cStr) > 0 and at('REPORT',cStr) >0 ;
  1217.                and at('OF',cStr) > 0
  1218.                this.cClass = trim( ltrim(  substr(cStr,at('CLASS',cStr)+5) ) )
  1219.                this.cClass = trim( ltrim(  substr(this.cClass,1, at(' OF ',this.cClass)-1) ) )
  1220.             endif
  1221.  
  1222.          until fRep.Eof() // until done with file
  1223.  
  1224.          this.oform.progress1.value = 25
  1225.  
  1226.          ////// clean up
  1227.          fRep.close()
  1228.          frep = Null
  1229.  
  1230.      
  1231.          ////// Copy Trans.gif - required for reports
  1232.          if not file(this.cCgiFolder+'Trans.gif')
  1233.             try
  1234.  
  1235.                copy file(this.oForm.cLoadPath+'Trans.gif') to ;
  1236.                     (this.cCGIFolder+'Trans.gif')
  1237.  
  1238.             catch (Exception e)
  1239.  
  1240.                msgbox('Unable to copy Trans.gif'+chr(13)+e.Message,;
  1241.                       'Copy Failed',16)
  1242.                return false
  1243.  
  1244.             endtry
  1245.  
  1246.          endif
  1247.  
  1248.       endif
  1249.  
  1250.      ////////// The following code is shared between all Wizard types
  1251.  
  1252.             ///// Create new .prg file
  1253.       if file(cPrgPath)
  1254.           dele file (cPrgPath)
  1255.       endif
  1256.       fPrg = new File()
  1257.       fPrg.Create(cPrgPath,'RA')
  1258.  
  1259.       this.oForm.progress1.value = 40
  1260.  
  1261.       n = len(cPrgName)+7  // to indent, for appearance only
  1262.  
  1263.       ////// header comments
  1264.       fPrg.Puts('/*  '+cPrgName+' - Program file for server-side CGI execution')
  1265.       fPrg.Puts(space(n)+'Generated by the Visual dBASE 7 '+;
  1266.                           this.oForm.cWizardType+' Web Wizard')
  1267.       fPrg.Puts(space(n)+'Date: '+dtoc(date())+' Time: '+time())
  1268.       fPrg.Puts('*/')
  1269.       fPrg.Puts(' ')
  1270.  
  1271.       ////// if Query, parse out the query string
  1272.       if this.oForm.cWizardType = 'Query'
  1273.          fPrg.Puts('////// Create query variable for response reports to use')
  1274.          fPrg.Puts('Public cSearch')
  1275.          fPrg.Puts('cSearch = " "')
  1276.          fPrg.Puts('cEnv = trim(GetEnv("QUERY_STRING"))')
  1277.          fPrg.Puts('if len(trim(cEnv)) > 0')
  1278.          fPrg.Puts('   cSearch = substr(cEnv,at("=",cEnv)+1)')
  1279.          fPrg.Puts('endif')
  1280.          fPrg.Puts('////// Remove terminating character, if any')
  1281.          fPrg.Puts('if at("%",cSearch) > 0')
  1282.          fPrg.Puts('   cSearch = substr(cSearch,1,at("%",cSearch)-1)')
  1283.          fPrg.Puts('endif') 
  1284.          fPrg.Puts('')
  1285.  
  1286.       elseif this.oForm.cWizardType = 'Data Entry'
  1287.  
  1288.          fPrg.Puts('private aData, cStr')
  1289.          fPrg.Puts('aData = new array()')
  1290.          fPrg.Puts('////// Get the Query string from the environment')
  1291.          fPrg.Puts('cStr = getenv("QUERY_STRING")')
  1292.          fPrg.Puts('if len(trim(cStr)) = 0')
  1293.          fPrg.Puts('   errorPage("Message: No data received from server!",0)')
  1294.          fPrg.Puts('endif')
  1295.          fPrg.Puts(' ')
  1296.          fPrg.Puts('////// Parse it out to get name/value pairs')
  1297.          fPrg.Puts('do while at("=",cStr) > 0')
  1298.          fPrg.Puts('   /////// CGI uses "&" separators between pairs')
  1299.          fPrg.Puts('   if at("&",cStr) > 0 // if more than one pair left')
  1300.          fPrg.Puts('      cData = OEMFormat(substr(cStr,1,at("&",cStr)-1))')
  1301.          fPrg.Puts('      cStr = substr(cStr,at("&",cStr)+1)')
  1302.          fPrg.Puts('      ////// If last pair ')
  1303.          fPrg.Puts('   else')
  1304.          fPrg.Puts('      cData = OEMFormat(cStr)    // take the whole string')
  1305.          fPrg.Puts('      cStr = " "')
  1306.          fPrg.Puts('   endif')
  1307.          fPrg.Puts(' ')
  1308.          fPrg.Puts('   if len(trim(cData)) > 0')
  1309.          fPrg.Puts('      aData.add(cData)')
  1310.          fPrg.Puts('   endif')
  1311.          fPrg.Puts('enddo')
  1312.          fPrg.Puts(' ')
  1313.          fPrg.Puts('/////// Sort array')
  1314.          fPrg.Puts('aData.Sort()')
  1315.          fPrg.Puts(' ')
  1316.          fPrg.Puts('////// Open Query or Data Module')
  1317.          if this.cDataType = 'Datamodule'
  1318.            fPrg.Puts('Set Procedure to '+this.cDataPath+' additive')
  1319.            fPrg.Puts('dMod = new '+cDModName+'()')
  1320.          else
  1321.            fPrg.Puts(cQueryName+' = new query()')
  1322.            cSql = 'Select * from '+'"'+this.cDataPath+'"'
  1323.            fPrg.Puts(cQueryName+'.sql = '+"'"+cSql+"'")
  1324.            fPrg.Puts(cQueryName+'.active = true')
  1325.          endif
  1326.          fPrg.Puts('////// sort array by query and field')
  1327.          fPrg.Puts('private n, cStr, bAppendDone, cQuery, cType, cRow')
  1328.          fPrg.Puts('cQuery = ""')
  1329.          fPrg.Puts('cType = ""')
  1330.          fPrg.Puts('cRow =""')
  1331.          fPrg.Puts('n=1')
  1332.          fPrg.Puts(' ')
  1333.          fPrg.Puts('////// Traverse array of field/value pairs and update')
  1334.          fPrg.Puts('////// rowset fields with data')
  1335.          fPrg.Puts(' ')
  1336.          fPrg.Puts('bAppendDone = false')
  1337.          fPrg.Puts(' ')
  1338.          fPrg.Puts('Do while n <= alen(aData,1)')
  1339.          fPrg.Puts('   ////// store array element for extraction')
  1340.          fPrg.Puts('   ////// format: Query*@Field=Data')
  1341.          fPrg.Puts('   cStr = trim(aData[n])')
  1342.          fPrg.Puts(' ')
  1343.          fPrg.Puts('   if at("=",cStr) > 0  // if a valid name/value pair')
  1344.          fPrg.Puts('      ////// extract query name')
  1345.          fPrg.Puts('      cQuery = substr(cStr,1,at("*@",cStr)-1)')
  1346.          fPrg.Puts('      ////// extract field name')
  1347.          fPrg.Puts('      cField = substr(cStr,at("*@",cStr)+2)')
  1348.          fPrg.Puts('      cField = substr(cField,1,at("=",cField)-1)')
  1349.          fPrg.Puts('      ////// extract data')
  1350.          fPrg.Puts('      cData  = trim(substr(cStr,at("=",cStr)+1))')
  1351.          fPrg.Puts('      ////// find out the type of the field to be updated')
  1352.          if this.cDataType = 'Datamodule'
  1353.             fPrg.Puts('      cRow = "dMod."+cQuery+".Rowset"')
  1354.          else
  1355.             fPrg.Puts('      cRow = cQuery+".rowset"')
  1356.          endif
  1357.          cQuote = "'"+'"'+"'"
  1358.          cF = "'.Fields['+"
  1359.          ct = "'].type'"
  1360.          cStr = 'cType = cRow + '+cF+cQuote+'+cField+'+cQuote+'+"].type"'             
  1361.          fPrg.Puts('      '+cStr)
  1362.          fPrg.Puts('      cType  = &cType')
  1363.          fPrg.Puts(' ')
  1364.          fPrg.Puts('      ////// try to append new row')
  1365.          fPrg.Puts('      if not bAppendDone')
  1366.          fPrg.Puts('         cAppend = cRow+".beginappend()"')
  1367.          fPrg.Puts('         try')
  1368.          fPrg.Puts('            &cAppend.')
  1369.          fPrg.Puts('         catch (Exception e)')
  1370.          fPrg.Puts('            errorPage(e.message,e.Lineno)')
  1371.          fPrg.Puts('         endtry')
  1372.          fPrg.Puts('      endif')
  1373.          fPrg.Puts('      bAppendDone = true')
  1374.          fPrg.Puts(' ')
  1375.          fPrg.Puts('      ////// Set up "update strings" for Macro ')   
  1376.          fPrg.Puts('      cUpdate = cRow')
  1377.          fPrg.Puts('      cF = '+cQuote+'+cField+'+cQuote)
  1378.          fPrg.Puts(' ')
  1379.          fPrg.Puts('      if cType     = "LOGICAL"')
  1380.          fPrg.Puts('         cUpdate += ".fields["+cF+"].value = "+iif(cData = "Y",true,false)')
  1381.          fPrg.Puts(' ')
  1382.          fPrg.Puts('      elseif cType = "NUMERIC" or ;')
  1383.          fPrg.Puts('         cType = "INTEGER" or ;')
  1384.          fPrg.Puts('         cType = "LONG"')
  1385.          fPrg.Puts('         cUpdate +=  ".fields["+cF+"].value = "+val(cData)')
  1386.          fPrg.Puts(' ')
  1387.          fPrg.Puts('      elseif cType = "DATE"')
  1388.          fPrg.Puts('         cUpdate += ".fields["+cF+"].value = "+dtoc(cData)')
  1389.          fPrg.Puts(' ')
  1390.          fPrg.Puts('      elseif cType = "AUTOINCREMENT"')
  1391.          fPrg.Puts('          // do nothing!! Autoincrement is automatic')
  1392.          fPrg.Puts(' ')
  1393.          fPrg.Puts('      else') 
  1394.          fPrg.Puts('      cUpdate += ".fields["+cF+"].value = "+'+cQuote+'+cData+'+cQuote)
  1395.          fPrg.Puts(' ')
  1396.          fPrg.Puts('      endif')
  1397.          fPrg.Puts('   endif')
  1398.          fPrg.Puts('   if cType # "AUTOINCREMENT"')
  1399.          fPrg.Puts('      Try')
  1400.          fPrg.Puts('         &cUpdate.  // Update field')
  1401.          fPrg.Puts('      Catch (Exception e)')
  1402.          fPrg.Puts('         ErrorPage(e.message, e.lineno)')
  1403.          fPrg.Puts('      endtry')
  1404.          fPrg.Puts('   endif')
  1405.          fPrg.Puts('   ++n')
  1406.          fPrg.Puts('   Local bSaveData')
  1407.          fPrg.Puts('   bSaveData = false')
  1408.          fPrg.Puts('   ////// if element beyond last one in array')
  1409.          fPrg.Puts('   if n > alen(aData,1)')
  1410.          fPrg.Puts('      bSaveData = true')
  1411.          fPrg.Puts('   else')
  1412.          fPrg.Puts('      ////// determine if data is for a new query')
  1413.          fPrg.Puts('      cStr = aData[n]')
  1414.          fPrg.Puts('      ////// find out what query the next element uses')
  1415.          fPrg.Puts('      cNewQuery = substr(cStr,1,at("*@",cStr)-1)')
  1416.          fPrg.Puts("      ////// if it's different than previous, save current row")
  1417.          fPrg.Puts('      bSaveData = ( cNewQuery # cQuery )')
  1418.          fPrg.Puts('   endif')
  1419.          fPrg.Puts('   if bAppendDone and bSaveData')
  1420.          fPrg.Puts('      cSave = cRow+".Save()"')
  1421.          fPrg.Puts('      &cSave.')
  1422.          fPrg.Puts('      bAppendDone = false  // reset for next query')
  1423.          fPrg.Puts(' ')
  1424.          fPrg.Puts('   endif')
  1425.          fPrg.Puts(' ')
  1426.          fPrg.Puts('enddo')
  1427.          fPrg.Puts(' ')
  1428.  
  1429.          fPrg.Puts('GenerateResponse()  // return response page to Browser')
  1430.          fPrg.Puts('return  // either response: error or thank you, quits.')
  1431.  
  1432.          fPrg.Puts('////////////////function GenerateResponse//////////////')
  1433.          fPrg.Puts('////////////////outputs "thank you" to CGI ////////////')
  1434.          fPrg.Puts('function GenerateResponse')
  1435.          fPrg.Puts('   If file("results.txt")')
  1436.          fPrg.Puts('      Delete file results.txt')
  1437.          fPrg.Puts('   Endif')
  1438.          fPrg.Puts(' ')
  1439.          fPrg.Puts('   fOut = new File()')
  1440.          fPrg.Puts('   fOut.Create("Results.txt","RA")')
  1441.          fPrg.Puts(' ')
  1442.          fPrg.Puts('   fOut.Puts("Content-type: text/html")')
  1443.          fPrg.Puts('   fOut.Puts(" ")')
  1444.          fPrg.Puts('   fOut.Puts("<HTML>")')
  1445.          fPrg.Puts('   fOut.Puts("<TITLE>Data Entered</TITLE>")')
  1446.          this.BackgroundImage= trim(this.oForm.BackGroundImageField.Value)
  1447.          fPrg.Puts('   fOut.Puts('+"'"+class::BuildBodyString()+"'"+')')
  1448.          fPrg.Puts('   fOut.Puts("<blockquote>")')
  1449.          cHtml = class::BuildHTMLString(this.oForm.TextOnResponsePage)
  1450.  
  1451.          if len(trim(cHtml)) = 0
  1452.             cHtml = 'Data entered successfully!'
  1453.          endif
  1454.          cHTML = '"'+class::SubstituteChars(cHTML)+'"'
  1455.  
  1456.          fPrg.Puts('   fOut.Puts('+cHtml+')')
  1457.          fPrg.Puts('   fOut.Puts("</Blockquote>")')
  1458.          fPrg.Puts('   fOut.Puts("</Body>")')
  1459.          fPrg.Puts('   fOut.Puts("</HTML>")')
  1460.          fPrg.Puts(' ')
  1461.          fPrg.Puts('   fOut.close()')
  1462.          fPrg.Puts('   Quit')
  1463.          
  1464.       endif // Data-Entry wizard           
  1465.  
  1466.       if this.oForm.cWizardType # 'Data Entry'
  1467.          fPrg.Puts('////// Set procedure to report file')
  1468.          fPrg.Puts('Set procedure to '+this.cReportName+'.rep additive')
  1469.          fPrg.Puts('')
  1470.          fPrg.Puts('////// Instantiate report and set properties for HTML output')
  1471.          fPrg.Puts('r         = new '+this.cClass+'()')
  1472.          fPrg.Puts('r.Output = 4 // HTML')
  1473.          fPrg.Puts('r.OutputFileName = "Report.txt"')
  1474.          fPrg.Puts('')
  1475.          fPrg.Puts('   ////// Run the report')
  1476.          fPrg.Puts('try')
  1477.          fPrg.Puts('   r.render()')
  1478.          fPrg.Puts('catch (Exception e)')
  1479.          fPrg.Puts('   ErrorPage(e.message)')
  1480.          fPrg.Puts('endtry')
  1481.  
  1482.          fPrg.Puts('////// Clean up')
  1483.          fPrg.Puts('r = false')
  1484.          fPrg.Puts('close proc '+this.cReportName)
  1485.          fPrg.Puts('')
  1486.          fPrg.Puts('////// See if report was rendered')
  1487.          fPrg.Puts('if not file("Report.txt")')
  1488.          fPrg.Puts('   ErrorPage(e.message)')
  1489.          fPrg.Puts('endif')
  1490.          fPrg.Puts('')
  1491.          fPrg.Puts('////// open report file')
  1492.          fPrg.Puts('fRep = new file()')
  1493.          fPrg.Puts('fRep.Open("Report.txt","R")')
  1494.          fPrg.Puts('')
  1495.          fPrg.Puts('////// Create new CGI response file')
  1496.          fPrg.Puts('')
  1497.          fPrg.Puts('if file("Results.txt")')
  1498.          fPrg.Puts('   dele file ("Results.txt")')
  1499.          fPrg.Puts('endif')
  1500.          fPrg.Puts('fOut = new file()')
  1501.          fPrg.Puts('fOut.Create("Results.txt","RA")')
  1502.          fPrg.Puts('')
  1503.          fPrg.Puts('////// read in report file after appending CGI header')
  1504.          fPrg.Puts('fOut.Puts("Content-type: text/html")')
  1505.          fPrg.Puts('fOut.Puts(" ")')
  1506.          fPrg.Puts('')
  1507.          fPrg.Puts('////// loop through report.txt and read into results.txt')
  1508.          fPrg.Puts('private cStr')
  1509.          fPrg.Puts('Do')
  1510.          fPrg.Puts('   cStr = fRep.Gets()')
  1511.          fPrg.Puts('   fOut.Puts(cStr)')
  1512.          fPrg.Puts('Until fRep.eof()')
  1513.          fPrg.Puts('' )
  1514.          fPrg.Puts('////// save results file')
  1515.          fPrg.Puts('fOut.close()')
  1516.          fPrg.Puts('fRep.close()')
  1517.          fPrg.Puts('////// all done')
  1518.          fPrg.Puts('Quit')
  1519.          fPrg.Puts('')
  1520.          fPrg.Puts('')
  1521.  
  1522.       endif
  1523.  
  1524.       // shared///////////////////////////////////////////////////
  1525.       fPrg.Puts('//////////// Function:   ErrorPage //////////////////////////)')
  1526.       fPrg.Puts('//////////// Purpose:    Returns error page if CGI fails //////')
  1527.       fPrg.Puts('//////////// Param:      cMess  = Error Message //////////////')
  1528.       fPrg.Puts('function ErrorPage(cMess,nLineNo)')
  1529.       fPrg.Puts('////// Create new results file') 
  1530.       fPrg.Puts('if file("Results.txt")')
  1531.       fPrg.Puts('   dele file ("Results.txt")')
  1532.       fPrg.Puts('endif')
  1533.       fPrg.Puts('nLineNo = iif(empty(nLineNo),0,nLineNo)')
  1534.       fPrg.Puts('fOut = new file()')
  1535.       fPrg.Puts('fOut.Create("Results.txt","RA")')
  1536.       fPrg.Puts('fOut.Puts("")')
  1537.       fPrg.Puts('////// Generate HTML error page')
  1538.       fPrg.Puts('fOut.Puts("Content-type: text/html")')
  1539.       fPrg.Puts('fOut.Puts(" ")')
  1540.       fPrg.Puts('fOut.Puts("<HTML>")')
  1541.       fPrg.Puts('fOut.Puts("<HEAD><Title>Visual dBASE 7 Web Wizard Error Page</Title>")')
  1542.       fPrg.Puts('fOut.Puts("<BODY>")')
  1543.       fPrg.Puts('fOut.Puts("")')
  1544.       fPrg.Puts('fOut.Puts("   <H2><I>Sorry,an error ocurred on the host!</I></H2>")')
  1545.       fPrg.Puts('fOut.Puts("")')
  1546.       fPrg.Puts('fOut.Puts("   <P>Error:"+cMess+" </P>")')
  1547.       fPrg.Puts('fOut.Puts("   <P>Line No.: "+ltrim(str(nLineNo,5))+"</p>")')
  1548.       fPrg.Puts('fOut.Puts("   <P>Press the back button and try again, or contact the Web'+;
  1549.                     'master for assistance")')
  1550.       fPrg.Puts('fOut.Puts("")')
  1551.       fPrg.Puts('fOut.Puts("</BODY>")')
  1552.       fPrg.Puts('fOut.Puts("</HTML>")')
  1553.       fPrg.Puts('fOut.close()')
  1554.       fPrg.Puts('Quit')
  1555.  
  1556.       fPrg.Puts(' ')
  1557.       fPrg.Puts('///////////// Function OEMFormat //////////////////////////////')
  1558.       fPrg.Puts('///////////// Purpose - transforms CGI escape chars to OEM/////')
  1559.       fPrg.Puts('///////////// Param: cStr - Environment Variable Value ////////')
  1560.       fPrg.Puts('function OEMFormat(cStr)')
  1561.       fPrg.Puts('   ////// remove terminating character')
  1562.       fPrg.Puts('   if at("%21",cStr) > 0')
  1563.       fPrg.Puts('      cStr = substr(cStr,1,at("%21",cStr)-1)')
  1564.       fPrg.Puts('   endif')
  1565.       fPrg.Puts('   ////// remove "Pluses" used as space keepers in CGI')
  1566.       fPrg.Puts('   do while at("+",cStr) > 0')
  1567.       fPrg.Puts('      cStr = substr(cStr,1,at("+",cStr)-1) + " "+;')
  1568.       fPrg.Puts('             substr(cStr,at("+",cStr)+1)')
  1569.       fPrg.Puts('   enddo')
  1570.       fprg.Puts('   ////// add in "pluses" sent as escape characters')
  1571.       fPrg.Puts('   do while at("%2B",cStr) > 0')
  1572.       fPrg.Puts('      cStr = substr(cStr,1,at("%2B",cStr)-1) + "+" +;')
  1573.       fPrg.Puts('             substr(cStr,at("%2B",cStr)+3)')
  1574.       fPrg.Puts('   enddo')
  1575.       fPrg.Puts('   ////// add in "ampersands" sent as escape characters')
  1576.       fPrg.Puts('   do while at("%26",cStr) > 0')
  1577.       fPrg.Puts('      cStr = substr(cStr,1,at("%26",cStr)-1) + "&"+;')
  1578.       fPrg.Puts('             substr(cStr,at("%26",cStr)+3)')
  1579.       fPrg.Puts('   enddo')
  1580.       fPrg.Puts('   return cStr')
  1581.       fPrg.Close() 
  1582.       fPrg = null
  1583.  
  1584.  
  1585.      
  1586.  
  1587.       private cBatPath
  1588.  
  1589.       ////// get full pathnames for .bat and .exe
  1590.       cBatPath = this.cCGIFolder+this.cReportName+'.bat'
  1591.  
  1592.       if file(cBatPath)
  1593.          dele file (cBatPath)
  1594.       endif
  1595.  
  1596.       cExePath = this.cCGIFolder+this.cReportName+'2.exe'
  1597.  
  1598.       fBat = new File()
  1599.       fBat.Create(cBatPath,'RA')
  1600.  
  1601.       fBat.Puts('@echo off')
  1602.       fBat.Puts('call '+this.cReportName+'2.exe')
  1603.       fBat.Puts('Type results.txt')
  1604.       fBat.Close()
  1605.       fBat = Null
  1606.  
  1607.       
  1608.       this.oForm.Finishlabel.text = 'Recompiling all files...'
  1609.       this.oForm.progress1.value = 80
  1610.  
  1611.       ////// re-compile all files
  1612.       for n =1 to alen(this.aObj,1)
  1613.  
  1614.          try
  1615.  
  1616.             if not empty(this.aObj[n])
  1617.                compile (this.aObj[n])
  1618.             endif
  1619.  
  1620.          catch (Exception e)
  1621.  
  1622.             msgbox(e.message,'Compile Failed: '+this.aObj[n],16)
  1623.             return false
  1624.  
  1625.          endtry
  1626.  
  1627.       next
  1628.  
  1629.       this.oForm.Finishlabel.text = 'Building .exe...'
  1630.       this.oForm.progress1.value = 90
  1631.  
  1632.       ////// Build a "build string"
  1633.       private cFile,cBuild
  1634.  
  1635.  
  1636.       cBuild = 'Build '+substr(this.aObj[1],1, len(this.aObj[1])-1)+'o'
  1637.  
  1638.  
  1639.       for n = 2 to alen(this.aObj,1)
  1640.           cFile = this.aObj[n]
  1641.           ////// paste the object file name
  1642.           cFile = '"'+substr(cFile,1,len(cFile)-1)+'o'+'"'
  1643.           cBuild += ' ,'+cFile
  1644.       next
  1645.  
  1646.       cBuild += ' To '+cExePath
  1647.  
  1648.  
  1649.  
  1650.       try
  1651.  
  1652.         &cBuild.
  1653.  
  1654.       catch (Exception e)     
  1655.  
  1656.         msgbox(e.message,'EXE Build Error',16)
  1657.         return false
  1658.  
  1659.       endtry
  1660.  
  1661.    
  1662.    return true
  1663.  
  1664.    function SubstituteChars(cStr)
  1665.  
  1666.    do while at("'",cStr) > 0
  1667.  
  1668.       cStr = substr(cStr,1,at("'",cStr)-1) +;
  1669.              '''+substr(cStr,at("'",cStr)+1)
  1670.  
  1671.    enddo
  1672.  
  1673.    do while at('"',cStr) > 0
  1674.  
  1675.       cStr = substr(cStr,1,at('"',cStr)-1) +;
  1676.              '"'+substr(cStr,at('"',cStr)+1)
  1677.  
  1678.    enddo
  1679.  
  1680.  
  1681.    return cStr
  1682. endclass
  1683.  
  1684.  
  1685.